package paper.web.controller.console;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintDeclarationException;
import javax.validation.Valid;
import javax.validation.Validator;

import keter.domain.Account;
import keter.domain.Role;
import keter.domain.validation.BeanValidators;
import keter.service.AccountService;
import keter.service.RoleService;
import keter.service.UnitService;
import keter.web.controller.KeterBaseController;
import keter.web.util.MediaTypes;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import paper.domain.User;
import paper.service.UserService;

@Controller
@RequestMapping("/console/account")
@PreAuthorize("hasAnyRole('ADMIN')")
public class AccountController extends KeterBaseController {

	@Autowired
	AccountService as;

	@Autowired
	RoleService rs;

	@Autowired
	UserService us;

	@Autowired
	UnitService uns;

	@Autowired
	private Validator validator;

	private static final Logger logger = LoggerFactory.getLogger(AccountController.class);

	public AccountController() {
	}

	public static class Views {
		private static final String Prefix = "console/account";
		static final String Index = to_(Prefix) + "index";
		static final String Add = to_(Prefix) + "add";
		static final String Update = to_(Prefix) + "update";
		static final String View = to_(Prefix) + "view";
		static final String Delete = to_(Prefix) + "delete";
	}

	/**
	 * <p>
	 * Method ：index
	 * <p>
	 * Description : 处理 /console/account请求，自动跳转到/console/account/index.jsp
	 * 
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 * @author gulixing@msn.com
	 * @version 1.0.0
	 */
	@RequestMapping(value = Routes.Index, method = RequestMethod.GET)
	public String index(ModelMap model) throws Exception {
		return Views.Index;
	}

	/**
	 * <p>
	 * Method ：add
	 * <p>
	 * Description : 进入增加页面
	 * 
	 * @return
	 * @author gulixing@msn.com
	 * @version 1.0.0
	 */
	@RequestMapping(value = Routes.GetAll, method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8)
	@ResponseBody
	public List<Account> getAll() throws Exception {
		return as.getDao().findAll();
	}

	@RequestMapping(value = Routes.Add, method = RequestMethod.GET)
	public String add(Model model) {
		model.addAttribute("account", new Account());
		model.addAttribute("allRoles", rs.all());
		return Views.Add;
	}

	/**
	 * <p>
	 * Method ：update
	 * <p>
	 * Description : 进入修改页面
	 * 
	 * @param model
	 * @param id
	 * @return @Valid Customer customer,BindingResult binder
	 * @author 顾力行-gulx@neusoft.com
	 */
	@RequestMapping(value = Routes.Update, method = RequestMethod.GET)
	public ModelAndView update(Model model, @PathVariable Long id) {
		ModelAndView mav = new ModelAndView(Views.Update);
		Account user = as.findById(id);
		model.addAttribute("user", user);
		// model.addAttribute("myRoles",user.getRoleList());
		model.addAttribute("allRoles", rs.all());
		return mav;
	}

	/**
	 * <p>
	 * Method ：add
	 * <p>
	 * Description :
	 * 
	 * @param model
	 * @return
	 * @author 顾力行-gulixing@msn.com
	 */
	@RequestMapping(value = Routes.Add, method = RequestMethod.POST)
	// consumes = MediaTypes.JSON
	@ResponseBody
	public Map<String, String> add(HttpServletRequest request,
			@RequestParam(value = "roleList") List<Long> checkedRoleList,
			HttpServletResponse response) {
		Map<String, String> ajaxMap = getAjaxMap();
		Account a = getAccountFromRequest(request);
		if (!as.validateUnique(a.getName())) {
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);// 400
			ajaxMap.put("message", "帐户[" + a.getName() + "]已存在，请使用其他名称！");
			return ajaxMap;
		}
		// bind roleList
		a.getRoleList().clear();
		for (Long roleId : checkedRoleList) {
			Role role = new Role(roleId);
			a.getRoleList().add(role);
		}
		User u = getUserFromRequest(request);
		BeanValidators.validateWithException(validator, a);
		BeanValidators.validateWithException(validator, u);
		Long id = as.getDao().saveEntity(a).getId();
		u.setId(id);
		us.getDao().save(u);
		return ajaxMap;
	}

	private Account getAccountFromRequest(HttpServletRequest request) {
		Account a = new Account();
		a.setName((String) request.getParameter("name"));
		a.setPassword((String) request.getParameter("password"));
		a.setRepeatPassword(a.getPassword());
		if (!StringUtils.isEmpty(request.getParameter("unit"))) {
			Long unitId = Long.valueOf((String) request.getParameter("unit"));
			a.setUnit(uns.getDao().findOne(unitId));
		}
		return a;
	}

	private User getUserFromRequest(HttpServletRequest request) {
		User user = new User();
		user.setName((String) request.getParameter("username"));
		user.setEmail((String)request.getParameter("email"));
		user.setPhone((String)request.getParameter("phone"));
		return user;
	}

	/**
	 * <p>
	 * Method ：updateHaha
	 * <p>
	 * Description : 执行修改
	 * 
	 * @param model
	 * @param user
	 * @return
	 * @author 顾力行-gulx@neusoft.com
	 */
	@RequestMapping(value = Routes.Update, method = RequestMethod.POST)
	public String updateUser(@Valid Account user, BindingResult binder, Model model,
			@RequestParam(value = "roleList") List<Long> checkedRoleList) {
		if (StringUtils.isEmpty(user.getName())) {
			throw new ConstraintDeclarationException("用户名不能为空");
		}
		// bindRoleList(user, checkedRoleList);
		as.update(user);
		model.addAttribute("saved", "success");
		return Views.Update;
	}

	@RequestMapping(value = Routes.Delete, method = RequestMethod.GET)
	public String delete(Model model, @PathVariable Long id) {
		as.delete(id);
		model.addAttribute("deleted", "success");
		return redirectToUrl(Views.Prefix);// 直接访问请求
	}

//	/**
//	 * <p>
//	 * Method ：processPasswordError
//	 * <p>
//	 * Description : 处理密码不一致错误 由于自定义校验注解位于User类声明处，因此无法得到“fieldError”
//	 * 
//	 * @param binder
//	 * @author gulixing@msn.com
//	 * @version 1.0.0
//	 */
//	private void processPasswordError(BindingResult binder) {
//		for (Iterator<ObjectError> iterator = binder.getGlobalErrors().iterator(); iterator
//				.hasNext();) {
//			ObjectError e = (ObjectError) iterator.next();
//			// 密码不一致错误，errorCode代码与自定义处理类名一致
//			if (e.getCode().equals("PasswordConstraint")) {
//				binder.rejectValue("repeatPassword", "errorCode", e.getDefaultMessage());
//			}
//		}
//	}
}